package com.voip.sipphone;

import gov.nist.javax.sip.address.SipUri;

import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by RXJ on 2018/1/19.
 */
public class Register {

    private static String username= SipPhone.username;
    public static String address = SipPhone.ipAddr;
    private static String method = Request.REGISTER;
    private static String uri = "sip:"+SipPhone.ipAddr;
    private static String password =SipPhone.password;
    private static String host = SipLayer.listener.getHost();
    private static int port = SipLayer.listener.getPort();


    /**
     * 注册第二次握手  进行数据传输
     * @param response
     */
    public static void sendRegister(Response response,ResponseEvent responseReceivedEvent) throws ParseException, InvalidArgumentException, SipException {

        //from 创建本地请求用户名地址 获取 第一次请求返回的中 fromheader 注意 需要tag一致
        FromHeader fromHeader= (FromHeader) response.getHeader("from");


        //创建 toHeader
        SipURI toAddress = SipLayer.listener.addressFactory.createSipURI(username, address);
        Address toNameAddress = SipLayer.listener.addressFactory.createAddress(toAddress);
        toNameAddress.setDisplayName(username);
        //to 请求头
        ToHeader toHeader = SipLayer.listener.headerFactory.createToHeader(toNameAddress, null);

        SipURI requestURI = SipLayer.listener.addressFactory.createSipURI(username, SipPhone.ipAddr);

        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        //创建 viaHeaders 根据 response 中获取
        ViaHeader viaHeader = (ViaHeader) response.getHeader("Via");

        viaHeaders.add(viaHeader);

        //创建 CALL_ID 根据 response 中获取
        CallIdHeader callIdHeader = (CallIdHeader) response.getHeader("Call-ID");

        //创建 cSeq  Request 为调用方法  i=2 为进行到 第二步
        CSeqHeader cSeqHeader = SipLayer.listener.headerFactory.createCSeqHeader(2L, Request.REGISTER);
        method=cSeqHeader.getMethod();

        //创建  Max_forwards 默认：70
        MaxForwardsHeader maxForwards = SipLayer.listener.headerFactory.createMaxForwardsHeader(70);


        //创建请求对象
        // 传递先前创建的所有元素来实例化实际的 SIP 消息本身。
        Request request = SipLayer.listener.messageFactory.createRequest(requestURI,
                Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
                toHeader, viaHeaders, maxForwards);

        //创建 Contact对象  Contact URI
        SipURI contactURI = SipLayer.listener.addressFactory.createSipURI(username, host);
        contactURI.setPort(port);
        Address contactAddress = SipLayer.listener.addressFactory.createAddress(contactURI);
        contactAddress.setDisplayName(username);
        ContactHeader contactHeader = SipLayer.listener.headerFactory.createContactHeader(contactAddress);
        //contactHeader.setParameter("rinstance","51cc0049780c161f");
        request.addHeader(contactHeader);

        //创建 user_agent对象
        List<String> userAgentList = SipPhone.setUserAgentHeader();
        UserAgentHeader userAgentHeader =SipLayer.listener. headerFactory.createUserAgentHeader(userAgentList);
        request.addHeader(userAgentHeader);

        //创建 Allow对象
        request = SipPhone.setAllowHeader_REGISTER(request,
                SipLayer.listener.headerFactory);

        // 创建 Express 对象
        ExpiresHeader expiresHeader = SipLayer.listener.headerFactory.createExpiresHeader(3600);
        request.addHeader(expiresHeader);

        // 从WWW-Authenticate header 获取信息
        WWWAuthenticateHeader wwwAuthenticateHeader =(WWWAuthenticateHeader)
                response.getHeader("WWW-Authenticate");
        String realm = wwwAuthenticateHeader.getRealm();
        String nonce = wwwAuthenticateHeader.getNonce();

        //从获取到的加密信息中保存到 验证信息中
        AuthorizationHeader authorizationHeader =
                SipLayer.listener.headerFactory.createAuthorizationHeader(uri);
        authorizationHeader.setScheme(wwwAuthenticateHeader.getScheme());
        authorizationHeader.setUsername(username);
        authorizationHeader.setRealm(realm);
        authorizationHeader.setNonce(nonce);
        authorizationHeader.setAlgorithm(wwwAuthenticateHeader.getAlgorithm());

        SipUri sipUri = (SipUri) SipLayer.listener.addressFactory.createURI(uri);
        authorizationHeader.setURI(sipUri);
        //计算 本地密码 获取 response
        authorizationHeader.setResponse(SipPhone.getResponse(
                username,realm,password,method,uri,nonce));
        request.addHeader(authorizationHeader);

        //发送请求

       /* ClientTransaction ct=SipLayer.listener.sipProvider.getNewClientTransaction(request);
        ct.sendRequest();*/

       SipLayer.listener.sipProvider.sendRequest(request);
      
    }


    /**
     * 发送注册请求
     */
    public static void sendRegister()
            throws ParseException, InvalidArgumentException, SipException {
        //from 创建本地请求用户名地址
        SipURI from = SipLayer.listener.addressFactory.createSipURI(username, address);
        Address fromNameAddress = SipLayer.listener.addressFactory.createAddress(from);
        fromNameAddress.setDisplayName(username);
        //创建 本地请求头
        // s 为 tag 参数
        FromHeader fromHeader = SipLayer.listener.headerFactory.createFromHeader(
                fromNameAddress, null);

        //to 请求用户名和地址

        SipURI toAddress = SipLayer.listener.addressFactory.createSipURI(username, address);
        Address toNameAddress = SipLayer.listener.addressFactory.createAddress(toAddress);
        toNameAddress.setDisplayName(username);
        //to 请求头
        ToHeader toHeader = SipLayer.listener.headerFactory.createToHeader(toNameAddress, null);

        SipURI requestURI = SipLayer.listener.addressFactory.createSipURI(username, address);

        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();

        //创建 via
        ViaHeader viaHeader = SipLayer.listener.headerFactory.createViaHeader(
                host, port, "udp", null);
        //viaHeader.setParameter("RPort","rport");
        viaHeaders.add(viaHeader);

        //创建 CALL_ID
        CallIdHeader callIdHeader = SipLayer.listener.sipProvider.getNewCallId();
        //创建 cSeq  Request 为调用方法
        CSeqHeader cSeqHeader =SipLayer.listener.headerFactory.createCSeqHeader(1L, Request.REGISTER);
        //创建  Max_forwards 默认：70
        MaxForwardsHeader maxForwards = SipLayer.listener.headerFactory.createMaxForwardsHeader(70);

        //创建请求对象
        // 传递先前创建的所有元素来实例化实际的 SIP 消息本身。
        Request request = SipLayer.listener.messageFactory.createRequest(requestURI,
                Request.REGISTER,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards);

        //然后向消息中添加其他元素：
        // Contact 头和消息的内容（负载）。此时也可以添加自定义头。
        //创建 Contact对象  Contact URI
        SipURI contactURI = SipLayer.listener.addressFactory.createSipURI(username, host);
        contactURI.setPort(port);
        Address contactAddress = SipLayer.listener.addressFactory.createAddress(contactURI);
        contactAddress.setDisplayName(username);
        ContactHeader contactHeader = SipLayer.listener.headerFactory.createContactHeader(contactAddress);
        request.addHeader(contactHeader);

        //创建 user_agent对象
        List<String> userAgentList = SipPhone.setUserAgentHeader();
        UserAgentHeader userAgentHeader = SipLayer.listener.headerFactory.createUserAgentHeader(userAgentList);
        request.addHeader(userAgentHeader);

        //创建 Allow对象
        request = SipPhone.setAllowHeader_REGISTER(request,SipLayer.listener.headerFactory);

        // 创建 Express 对象
        ExpiresHeader expiresHeader = SipLayer.listener.headerFactory.createExpiresHeader(3600);
        request.addHeader(expiresHeader);

        //发送请求
        //sipProvider.sendRequest(request);
        System.out.println("发起注册请求");
       /* ClientTransaction ct = SipLayer.listener.sipProvider.getNewClientTransaction(request);
        SipLayer.listener.calleeDialog = ct.getDialog();
        SipLayer.listener.clientTransaction = ct;
        ct.sendRequest();*/

        SipLayer.listener.sipProvider.sendRequest(request);


    }
}
